package com.kern.rpc.server;

import com.kern.rpc.bean.Request;
import com.kern.rpc.bean.Response;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 *  接收客户端发过来的请求, 从接收的对象中获取要执行方法的接口和方法的信息
 * Created by caoshi at 20:36 2021-07-18
 */
public class RpcServerService implements Runnable {

    private Socket socketClient;    // 客户端socket
    private Map<String, Class> serviceRegistry = new HashMap<>();

    private Response response = new Response();

    public RpcServerService(Socket socketClient) {
        super();
        this.socketClient = socketClient;
    }

    @Override
    public void run() {
        try {
            OutputStream out = socketClient.getOutputStream();
            InputStream in = socketClient.getInputStream();

            ObjectInputStream objIn = new ObjectInputStream(in);
            ObjectOutputStream objOut = new ObjectOutputStream(out);

            // 获取请求参数
            Object param = objIn.readObject();
            Request request = null;
            if (!(param instanceof Request)) {
                response.setMessage("参数错误");
                objOut.writeObject(response);
                objOut.flush();
            } else {
                request = (Request) param;
            }

            System.out.println("执行的对象类型为 " + request.getClassName());

            // 注册服务
            Class service = serviceRegistry.get(request.getClassName());
            if (service != null) {
                Method method = service.getMethod(request.getMethodName(), request.getParamTypes());
                Object result = method.invoke(service.newInstance(), request.getParams());
                // 返回结果
                response.setObj(result);
            }
            objOut.writeObject(response);
            objOut.flush();
            objOut.close();
            in.close();
            socketClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void registerService(Class iface, Class impl) {
        this.serviceRegistry.put(iface.getName(), impl);
    }

}
